Input = {}



function Input:___init()
    self.___joy = nil
    self.___cache = {
        Axis = {},
        Button = {}
    }
    self.___callbacks = {
        ButtonPressed = function(b)  end,
        ButtonReleased = function(b)  end
    }
    self.___start_listen = false
    self.printError = true


    for i = 1, 6 do
        self.___cache.Axis[i] = 0
    end

    for i = 1, 15 do
        self.___cache.Button[i] = false
    end
end

function Input:BindButtonCallback(type, f)
    if type == "Pressed" then
        self.___callbacks.ButtonPressed = f
    elseif type == "Released" then
        self.___callbacks.ButtonReleased = f
    end
end

function Input:BindController(joy)
    self.___joy = joy
end

function Input:Update()
    local stat, exp = pcall(self.___update, self)
    if not stat and self.printError then
        print("[Input Update][Error]: \n  "..exp.."\n")
    end
end

function Input:___listen()
    self.___start_listen = true
    while self.___joy ~= nil and self.___start_listen do
        self:Update()
        os.sleep(0.05)
    end
end

function Input:Close()
    self.___start_listen = false
end

function Input:___update()
    for i = 1, 6 do
        self.___cache.Axis[i] = self.___joy.getAxis(i)
    end
    local tmp = false
    for i = 1, 15 do
        tmp = self.___joy.getButton(i)
        if not self.___cache.Button[i] and tmp then
            self.___callbacks.ButtonPressed(i)
        elseif self.___cache.Button[i] and not tmp then
            self.___callbacks.ButtonReleased(i)
        end
        self.___cache.Button[i] = tmp
    end
end

function Input:GetAxis(A)
    return self.___cache.Axis[A]
end

function Input:GetButton(B)
    return self.___cache.Button[B]
end

function Input:StartListen(wait_for_all)
    local f = function()
        self:___listen()
    end
    if wait_for_all then
        parallel.waitForAll(f)
    else
        parallel.waitForAny(f)
    end
end

function Input:NewChannel()
    local obj = {}
    setmetatable(obj,self)
    self.__index = self

    obj:___init()

    return obj
end

return Input